<?php

/**
 * @author Nguyen Xuan Hong
 * @copyright 2010
 */

class clsDbTable
{	
	// Object property store
	var $attList = array();		
	// Table name
	var $table;
	
	// Overload method get properties value [@new version 4.0]
	function __get($property){
		if(array_key_exists($property,$this->attList)){
			return $this->attList[$property]['value'];
		}
		else {
			//echo("Error acesses to properties <b>$property</b>");
		}
	}
	
	// Overload method set properties value [@new version 4.0]
	function __set($property,$value){
		if(array_key_exists($property,$this->attList)){
			$this->attList[$property]['value'] = $value;
		}
		else {
			//echo("Error acesses to properties <b>$property</b>");
		}
	}
	
	// Object list function @for overwrite
	function objlist($pkname,$condition = array(),$countmode = false){
		/* Examplecondition
			$condition = array(
				'display'	=> 	1,
				'@find' => array(
					'title'		=>	$kw,
					'ustitle'	=>	$kw					  
				)	
				'@limit' 	=> 	0,
				'@begin'	=>	1,	
				'@orderby'	=>	'id',
				'@ordermode'=>	'DESC'
				)	
			);
		*/
		//#FB::info($condition );
		foreach ($condition as $key => $value){
			if(substr($key,0,1)=='@'){
				if($key == '@find'){
					foreach($condition['@find'] as $ckey => $cvalue){
						$searchquery .=" OR " .$this->attList[$ckey]['column'] . " LIKE '%" . ascii_convert($cvalue) . "%' ";	
						//#FB::info($searchquery);
					}
				}
				continue;
			}
			if(strpos($key,'#')!== false && strpos($key,'#')==0){
				continue;
			}
			$querycondition .= " AND " .$this->attList[$key]['column'] . " = '" . $condition[$key] . "' ";	
			
			/*
			
			
			if(  strpos($key,'@')==0  && strpos($key,'@')!== false  ){
				if($key == '@find'){
					foreach($condition['@find'] as $ckey => $cvalue){
						$searchquery ." AND " .$attList[$ckey]['column'] . " LIKE '%" . $cvalue . "%' ";	
					}
				}
				continue;
			}
			else if(  strpos($key,'#')==0  && strpos($key,'#')!== false  ){
				#FB::info('sax');//$querycondition .= " AND " .$attList[$key]['column'] . " = '" . $condition[$key] . "' ";	
				continue;
			}
			else {
				#FB::info('sa');
				// simplecondition
				$querycondition .= " AND " .$attList[$key]['column'] . " = '" . $condition[$key] . "' ";	
			}*/
		}
		
		// parsed data ! create query and condition
		if($searchquery) $searchquery = ' AND (0'.$searchquery.') ';
		$limitString = ($condition['@limit']) ? " LIMIT " . (int)$condition['@begin'] . "," . $condition['@limit'] . " " : "";
		/*
		if(!$condition['@limit'] && $condition['@begin']){
			$limitString = " LIMIT " . $condition['@begin'] . ",0 ";
		}
		*/
		
		
		if($condition['@orderby']){
			//#FB::warn($condition['@orderby']);
			if($condition['@orderby'] == 'rand'){
				$orderquery = ' ORDER BY RAND() ' . ($condition['@ordermode']);
			}else{
				$orderquery = ' ORDER BY `'. $this->attList[$condition['@orderby']]['column'] .'` ' . ($condition['@ordermode']);
			}
		}
		foreach($this->attList as $key => $value){
			if($this->attList[$key]['column']){
				$columnlist.= ',`'.$this->attList[$key]['column'].'`';
			}
		}
		$columnlist = substr($columnlist,1);
		// full clsMySQL query
		if($countmode){
			$columnlist = "COUNT($pkname) AS cntresult";
		}
		$fullquery = "SELECT $columnlist FROM `". $this->table ."` WHERE 1 ".$searchquery.$querycondition.$orderquery.$limitString;
		//#FB::info('-----'.$fullquery);
		$pClsMySQL = new clsMySQL;
		$q = $pClsMySQL->query($fullquery);
		if($countmode){
			$fa = $pClsMySQL->fetch_array($q);
			return (int)$fa['cntresult'];
		}
		$classname = get_class($this);
		while($fa = $pClsMySQL->fetch_array($q)) {
			$cache = new $classname();
			$cache->assignToCache($fa);
			$returnObject[$fa[$this->attList[$pkname]['column']]] = $cache;
		}
		return $returnObject;
	}
	
	
	function objquery($pkname,$fullquery){
		$pClsMySQL = new clsMySQL;
		$q = $pClsMySQL->query($fullquery);
		$classname = get_class($this);
		while($fa = $pClsMySQL->fetch_array($q)) {
			$cache = new $classname();
			$cache->assignToCache($fa);
			$returnObject[$fa[$this->attList[$pkname]['column']]] = $cache;
		}
		return $returnObject;
	}
	
	function coutquery($fullquery,$cname = 'cnt'){
		$pClsMySQL = new clsMySQL;
		$q = $pClsMySQL->query($fullquery);
		$fa = $pClsMySQL->fetch_array($q);
		return $fa['cnt'];
	}
	
	
	function countlist($pkname,$condition = array()){
		return $this->objlist($pkname,$condition,true);
	}
	
	// Get object attribute value [@oldversion]
	function value($attributeName){
		return $this->attList[$attributeName]['value'];
	}
	
	// Get object attribute value [@oldversion]
	function setvalue($attributeName,$value){
		$this->attList[$attributeName]['value'] = $value;
	}
	
	// error store value
	var $hasError = array();
	
	// update object [attribute name , attribute value]
	function updateDB($name1 = "" , $value1 = "", $name2 = "" , $value2 = "", $name3 = "" , $value3 = "")
	{
		if($this->hasError)	 
		{
			return false;
		}
		$condition = "true";
		$condition1 = "";
		$condition2 = "";
		$condition3 = "";
		if($name1) 
		{
			$columnName = $this->attList[$name1]['column'];
			if(!$columnName) return false;
			if($value1) 
			{
				$condition1 = $columnName ." = '". $value1 ."' ";
			}
			else 
				$condition1 = $columnName ." = '". $this->attList[$name1]['value'] ."' ";
		}
		if($name2) 
		{
			$columnName = $this->attList[$name2]['column'];
			if(!$columnName) return false;
			if($value2) 
			{
				$condition2 = $columnName ." = '". $value2 ."' ";
			}
			else 
				$condition2 = $columnName ." = '". $this->attList[$name2]['value'] ."' ";
		}
		if($name3) 
		{
			$columnName = $this->attList[$name3]['column'];
			if(!$columnName) return false;
			if($value3) 
			{
				$condition3 = $columnName ." = '". $value3 ."' ";
			}
			else 
				$condition3 = $columnName ." = '". $this->attList[$name3]['value'] ."' ";
		}
		
		if($condition1 != "" && $condition2 != "" && $condition3 != "")
			$condition = $condition1." AND ".$condition2." AND ".$condition3;
		else if($condition1 != "" && $condition2 != "")
			$condition = $condition1." AND ".$condition2;
		else if($condition1 != "" && $condition3 != "")
			$condition = $condition1." AND ".$condition3;
		else if($condition2 != "" && $condition3 != "")
			$condition = $condition2." AND ".$condition3;
		else if($condition1 != "")
			$condition = $condition1;
		else if($condition2 != "")
			$condition = $condition2;
		else if($condition3 != "")
			$condition = $condition3;
			
		foreach ($this->attList as $key=>$arr) {
			
			if (!$arr['column']) continue;	// Nếu không tồn tại cột thì thôi
			if ( $arr['value'] == '' && ($arr['null'] != true)) continue;	# Buộc phải có giá trị				
			if ($arr['change_on_update'] && $arr['value'] == '') continue ;	# Chỉ thay đổi khi update
			if ($arr['update_if_true'] && !eval('return ('.$arr['update_if_true'].');')) continue;	# Thay đổi khi đúng			
			
			$s1 .= $arr['column'].' = \''.$arr['value'].'\', ';
			//else $s1 .= $arr['column'].' = \"$'.$key.'\", ';
		}
		$s1 = substr($s1,0,-2);
		if ($condition) $sql = "UPDATE ". $this->table ." SET ".$s1." WHERE $condition LIMIT 1";
		else $sql = "UPDATE ". $this->table ." SET ".$s1."";
		$pClsMySQL = new clsMySQL;
		$pClsMySQL->query($sql);
		return true ;
	}
	
	// remove object [attribute name]
	function removeDB($name = ""){
		//if($this->hasError)	 return false;
		$pClsMySQL = new clsMySQL;
		$condition = $this->attList[$name]['column'] ." = '". $this->value($name) ."' ";
		$query  = "DELETE FROM ". $this->table ." WHERE $condition LIMIT 1";
		$pClsMySQL->query($query);
		# Foreach
	}
	
	// insert object to database
	function insertDB(){
		if($this->hasError)	 return false;
		foreach ($this->attList as $key => $arr) {
			if (!$arr['column']) continue;
			if (!$arr['type'] && ($arr['value']=="")) continue;
 			if (!$arr['value'] && ($arr['null'] != true)) continue;
			if ($arr['update_if_true'] && !eval('return ('.$arr['update_if_true'].');')) continue;
			#if ($arr['type'] == 'hidden_value' && !$arr['change_on_update']) continue;			
			$s1 .= '`'.$arr['column'].'`,';
			if ($arr['type'] == 'hidden_value')	$s2 .= '\''. htmlspecialchars($arr['value']).'\',';
			else $s2 .= '\''.$arr['value'].'\',';
		}
		$s1 = substr($s1,0,-1);
		$s2 = substr($s2,0,-1);
		$sql = "INSERT INTO ". $this->table ." (".$s1.") VALUES (".$s2.")";
		$pClsMySQL = new clsMySQL;
		$pClsMySQL->query($sql);
		$id = mysql_insert_id();
		$this->setvalue("id", $id);
		return true;
	}
	
	// load object attribute value from database [attribute name . attribute value]
	function loadDB($name1 = "" , $value1 = "", $name2 = "" , $value2 = "", $name3 = "" , $value3 = "") 
	{
		$condition = "true";
		$condition1 = "";
		$condition2 = "";
		$condition3 = "";
		if($name1) 
		{
			$columnName = $this->attList[$name1]['column'];
			if(!$columnName) return false;
			if($value1) 
			{
				$condition1 = $columnName ." = '". $value1 ."' ";
			}
			else 
				$condition1 = $columnName ." = '". $this->attList[$name1]['value'] ."' ";
		}
		if($name2) 
		{
			$columnName = $this->attList[$name2]['column'];
			if(!$columnName) return false;
			if($value2) 
			{
				$condition2 = $columnName ." = '". $value2 ."' ";
			}
			else 
				$condition2 = $columnName ." = '". $this->attList[$name2]['value'] ."' ";
		}
		if($name3) 
		{
			$columnName = $this->attList[$name3]['column'];
			if(!$columnName) return false;
			if($value3) 
			{
				$condition3 = $columnName ." = '". $value3 ."' ";
			}
			else 
				$condition3 = $columnName ." = '". $this->attList[$name3]['value'] ."' ";
		}
		
		if($condition1 != "" && $condition2 != "" && $condition3 != "")
			$condition = $condition1." AND ".$condition2." AND ".$condition3;
		else if($condition1 != "" && $condition2 != "")
			$condition = $condition1." AND ".$condition2;
		else if($condition1 != "" && $condition3 != "")
			$condition = $condition1." AND ".$condition3;
		else if($condition2 != "" && $condition3 != "")
			$condition = $condition2." AND ".$condition3;
		else if($condition1 != "")
			$condition = $condition1;
		else if($condition2 != "")
			$condition = $condition2;
		else if($condition3 != "")
			$condition = $condition3;
			
		$pClsMySQL = new clsMySQL;
		$query  = "SELECT * FROM ". $this->table ." WHERE $condition LIMIT 0,1";
		##FB::info("LOADDB : $query");
		$q = $pClsMySQL->query($query);
		$r = $pClsMySQL->fetch_array($q);
		foreach ($this->attList as $key => $arr) {
			if($this->attList[$key]['unload']) continue;
			$this->attList[$key]['value'] = (($r[$arr['column']]));
			# #FB::info("Read : $key ->value =  ".$r[$arr['column']]);
		}
	}
	
	/*
	// remove attribute 
	function unuseAttribute($list = array()){
		if(sizeof($list))
		foreach($list as $key){
			unset($this->attList[$key]);
		}
	}
	
	function useAttribute($list = array()){
		if(sizeof($list))
		foreach($this->attList as $key => $val){
			if(!in_array($key,$list)) unset($this->attList[$key]) ;
		}
	}
	*/
	
	// rename use and unuse attr [@new version 4.0]
	function remattr($params){
		$list = explode(",",$params);
		if(sizeof($list))
		foreach($list as $value){
			unset($this->attList[$value]);
		}
	}
	
	function useattr($params){
		$list = explode(",",$params);
		if(sizeof($list))
		foreach($this->attList as $key => $val){
			if(!in_array($key,$list)) unset($this->attList[$key]);
		}
	}
	
	function recvattr($id = 'id'){
		$classname = get_class($this);
		$prv_obj = new $classname($this->value($id));
		$this->attList = $prv_obj->attList;
	}
	

	// Field exist function
	// Return true if field exist
	// @Param : <colum ID name>	<ID value>
	function fieldExist($columnIDName,$idValue) {
		# #FB::info("CHECK field exist $columnIDName,$idValue");
		$pClsMySQL = new clsMySQL;
		$column = $this->attList[$columnIDName]['column'];
		if ($pClsMySQL->query_first("SELECT $column FROM ". $this->table ." WHERE $column = '". $idValue ."'"))
			return true ;
		return false;
	}
	
	// Field exist function
	// Return true if field exist
	// @Param : <colum ID name>	<ID value>
	function existAppend($columnIDName,$idValue) {
		# #FB::info("CHECK field exist $columnIDName,$idValue");
		$pClsMySQL = new clsMySQL;
		$column = $this->attList[$columnIDName]['column'];
		$ret = $pClsMySQL->query_first("SELECT * FROM ". $this->table ." WHERE $column = '". $idValue ."'");
		if($ret) return $ret;
		return false;
	}
	
	# Assign value of database to cache
	# @Param : <colum ID name>	<ID value>
	function assignToCache($arrayValue = array(),$columnIDName = "",$idValue = 0) {
		$columnIDName = $this->attList[$columnIDName]['column'];
		if (!$arrayValue) {
			$pClsMySQL = new clsMySQL;
			$datav = $pClsMySQL->query_first("SELECT * FROM ". $this->table ." WHERE $columnIDName = '". $idValue ."'");
		}
		else {
			$datav = $arrayValue;
		}
		foreach ($this->attList as $key => $value) {
			if($value['type'] == 'private') continue ;
			# Value type is default in database
			$this->attList[$key]['value'] =  $datav[$value['column']];
		}
		return true;
	}
	
	
	function loadBuffer($method = "POST"){
		#FB::info("Load form buffer");
		foreach($this->attList as $key => $arr){
			if (!$arr['type']) continue ;
			if($method == "POST")
				$value = spost($key);
			else 
				$value = sget($key);
			if($this->attList[$key]['number'] || $this->attList[$key]['type']=="check"){
				$value  = (int) $value;
			}
			#FB::send("Buffer $key : $value ");
			$this->attList[$key]['value'] = $value;
		}
		return true ;
	}
	
	
	
	var $formTemplates ;
	
	
	# Avaible submit check data intergirty
	# Require form class if not avaible
	function avaibleSubmit($method = "POST"){
		##FB::info("Check avaible submit");
		if (!class_exists('clsForm'))	require_once('form.php');
		$form = new clsForm($this->attList);
		return $form->avaibleSubmit($method);
	}
	
	function createForm($ftitle,$fname = 'autoform',$faction = '',$config = array()){
		if (!class_exists('clsForm'))	require_once('form.php');
		$form = new clsForm($this->attList);
		$form->hasError =  $this->hasError;
		$form->redefineTemplates = $this->formTemplates;
		return $form->createForm($ftitle,$fname,$faction,$config);
	}
	
	
	function arrTemplates($prefix){
		$arr = array();
		foreach($this->attList as $key => $value) {
			$arr['{'.$prefix.'.'.$key.'}'] = $this->value($key);
		}
		return $arr;
	}
	
	
	
	
	
	
	
	
	
	function sourceToCache(){
		
	}
	
	
	
	function putError($errInfo,$type = ""){
		$errorFormat = array(
			'error-code'	=> ($errInfo['code']) ? $errInfo['code']  : '0x00000A',
			'error-page'	=> ($errInfo['page']) ? $errInfo['page']  : 'Function control',
			'error-message'	=> ($errInfo['msg'])  ? $errInfo['msg']   : 'No information',
		);
		
		switch($type){
			case "json":
				return array2json($errorFormat);
			break;
			case "html":
				$tmp = '<div style="font-family:Tahoma, Geneva, sans-serif;font-size:11px; background-color:#FFF; border:dashed 1px; -moz-border-radius:5px;  border-radius: 5px; padding:30px; marign:10px;">
	<p><strong>Error code</strong> : {error-code}</p>
	<p><strong>Page</strong> : {error-page}</p>
	<p><strong>Message</strong> : {error-message}</p>
</div>';
				return replace_block_all($tmp,$errorFormat);
			break;
			default :
				$tmp = '<p><strong>Error code</strong> : {error-code}</p>
	<p><strong>Page</strong> : {error-page}</p>
	<p><strong>Message</strong> : {error-message}</p>';
				return replace_block_all($tmp,$errorFormat);
			break;
		}
	}
	
	function putArray(&$tpl,$eName){
		foreach($this->attList as $key => $val){
			$tpl[$eName][$key] = $this->value($key);
		}
	}
	
	function getfile($fileName){		
		$i = 0 ;
		for ($i = 0; $i<3; $i++) {
			if( @file_exists($fileName) )	{
				$CF = @fopen ($fileName, "r");
				$get = @fread ($CF,@filesize ($fileName));
				@fclose ($CF);
				return $get ;
			}
		}
		$this->hasError['str'] = "Không đọc được template";
		return false ;
	}
	
	function setFormTpl($input){
		$this->formTemplates = $input;
	}
}